Application Programming Interface的縮寫,主要在I,一個接口一個介面,能讓兩個軟體間相互溝通通。
Interface。其實生活中到處充滿了I,正在看這篇文章的你,因為電腦這個介面,讓你能讀取到iT邦幫忙的網頁及其DB裡的資料。在7-11點咖啡,店員點用咖啡機上的按鈕,讓咖啡機產生咖啡,那些按鈕就是一個介面。這些介面讓我們能直接操作機器,而不是還要使用者寫一段程式,咖啡機才會磨咖啡。
當專案,不管是用Rails、Django、Yii或任何語言編寫,如果想要有地圖顯示功能,那可能要去串接Map API,如果是想要能上傳圖片、音樂或影片,那可能要去串接雲端 API,有這些API後當網頁送出資料給Map或雲端時,他們才會知道你發出的資料是什麼,並做正確處理,當然有的會傳給資料給你,也因為有API才能轉換成我們專案想要的資料。
無論是因為興趣還是因為要吃飯寫code,總有一天要會寫
當功能越成熟時,總會希望使用者越來越多,但每個使用者的介面也不一定相同,iOS、Android、或PC,為網站建立一個API能方便讓任何介面的軟體開發者串接,進而使用到網站的功能,在這網路超發達的時代,已經是必要的事了。
API會不會太殺雞用牛刀?Rails 5 有了only API模式,API撰寫目前主流風格是REST API,就是**Rails是一個非常RESTful的框架**的那個REST,圍繞在資源(Resource)來做CRUD的操作,所以使用過Rails後再以Rails製作API非常容易上手。
請注意,我是用API-Only,如果之後還想回頭做View會很痛苦!
今天會先做到可以show與create,明天完整CRUD,後天認證。
$ rails new api-test --api
Git沒skip的話。$ git add --all
$ git commit -m "Initial commit"
能推上Github的話也不錯。
API controller。API的設計上通常不會用破壞性的方式去增加功能,網路上資料常看到這句話,簡單一點理解,API是讓其他開發人員串接的,不應該破壞原本功能而去增加新功能,保持靈活性,將功能慢慢往上加,不會突然皆捨去一個功能,也因此常常一開始就會給予版本號。
$ rails g controller api/v1/articles index show --no-test-framework
良好的API也需要有做test才對。
適當利用generate,全手動也是很好,但就失去了用Rails作API超方便這點了。
會自動生成app/controllers/api/v1這個資料夾。裡面有articles_controller.rb這個檔案。
class Api::V1::ArticlesController < ApplicationController
def index
end
def show
end
end
config/routes.rb會自動有以下內容。
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
get 'articles/index'
get 'articles/show'
end
end
end
routes.rb。少一個create。
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :articles, only: [:index, :show, :create]
end
end
end
其實不only也可以,之後就解開了。
Model還有Migrationˇ檔案。rails g model article title author description
我自己是會慣性檢查Migration檔案,這邊不秀出來了。
一樣記得。
$ rails db:create
$ rails db:migrate
controller內容。就跟CRUD流程差不多,這邊就不一步一步分開操作了,會直接show寫好的code。
如果真的有萌新參考到這篇文章,請記得自己手動打,3Q。
關於CRUD,搬出初學神書為你自己學Ruby on Rails。
class Api::V1::ArticlesController < ApplicationController
before_action :find_article, only: [:show]
#GET
def index
@articles = Article.all
render json:@articles, status: 200
end
#GET
def show
begin @article
render json: @article, status: 200
rescue
render json: {error: "article not found!"}
end
end
#POST
def create
@article = Article.new(article_params)
if @article.save
render json: @article, status: 200
else
render json: {erroe: "create failed"}
end
end
private
def find_article
@article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(
:title,
:author,
:description
)
end
end
真的是CRUD。
不過可以盡量要回傳訊息,尤其是失敗,當自己在串別人API,失敗了一點反應都沒有時,會很痛苦。
IRB測試一下吧。拖一下台錢,其實可以直接請seed建立資料了。
2.7.3 :001 > test_date = Article.new(title: "第一個故事", author: "nauosika", description: "今天從零開始學寫API, 好興奮呀! 興奮到模糊!")
=> #<Article id: nil, title: "第一個故事", author: "nauosika", description: "今天從零開始學寫API, ...
2.7.3 :002 > test_date.save
TRANSACTION (0.3ms) BEGIN
Article Create (6.9ms) INSERT INTO "articles" ("title", "author", "description", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["title", "第一個故事"], ["author", "nauosika"], ["description", "今天從零開始學寫API, 好興奮呀! 興奮到模糊!"], ["created_at", "2021-09-15 13:37:38.702287"], ["updated_at", "2021-09-15 13:37:38.702287"]]
TRANSACTION (5.5ms) COMMIT
=> true
2.7.3 :003 > test_date
=> #<Article id: 1, title: "第一個故事", author: "nauosika", description: "今天從零開始學寫API, 好興奮呀! 興奮到模糊!", created_at: "2021-09-15 13:37:38.702287000 +0000", updated_at: "2021-09-15 13:37:38.702287000 +0000">
好的第一小步確定完成了,專案已經可以正常建立資料。
rails s後,其實這樣已經可以看到資料了,但由於用api only模式,非常....不好看。
如果是用chrome可以接安裝擴充功能JSON Formatter。
畫面瞬間會順眼很多,這邊就不展示了。
雖然沒必要,還是請faker幫忙吧,不然手打假資料真的好累。
10.times do
Article.create(
title: Faker::Artist.name,
author: Faker::FunnyName.name,
description: Faker::Lorem.sentences)
end
$ rails db:seed
rails s。正常會有以下畫面。

明天會繼續完成整個CRUD,以及利用Postman來操作。
今天的leetcode198. House Robber
題目連結:https://leetcode.com/problems/house-robber/
題目重點:指針題。
如果不能連續拿兩間的錢,那就看從中間一點的房子往前看,不拿隔壁那間,看前兩間誰多,拿錢多那間,一直由此模式
紀錄就不會觸發警報了,最後拿紀錄最高的那間。
$ #第一間左邊沒人,不做紀錄。
[ 2, 7, 9, 3, 1 ]
$ #第二間左邊有人,但鄰居隔壁沒有兩間作比較,不做紀錄。
[ 2, 7, 9, 3, 1 ]
$ #第三間左邊有人,但鄰居隔壁只有一間2作比較,那就記錄+2下來。
[ 2, 7, 9, 3, 1 ]
11 # 9 + 2 = 11 , num[2] += num[0]
$ #第四間鄰居隔壁有兩間7與2作比較,那就記錄+7下來。
[ 2, 7, 9, 3, 1 ]
11 10 # 3 + 7 = 10,
$ #第五間鄰居隔壁有兩間11與7作比較,那就記錄+11下來。
[ 2, 7, 9, 3, 1 ]
11 10 12 # 1 + 11 = 12,
原本打算由nums[2],也就是9開始跑迴圈,但是無法滿足要做鄰居隔壁兩間作比較這件事。
nums[i] += [num[i - 2], num[ i - 3]].min #i = 2 時不成立。
那就2那間,前面多給一間0的就好了。
2.7.3 :234 > [2,7,9,3,1].unshift(0)
=> [0, 2, 7, 9, 3, 1]
這樣由9開始時。
nums[i] += [num[i - 2], num[ i - 3]].min #成立
# @param {Integer[]} nums
# @return {Integer}
def rob(nums)
nums.unshift(0)
(3..(nums.size - 1)).each do |i|
nums[i] += [nums[i-2], nums[i-3]].max
end
nums.max
end
這樣就ok了,(3..(nums.size - 1))覺得太醜可以改`(3...nums.size)。